import { Matrix2 } from './Matrix2';
/**
 * Copyright  2025, Hai Yue Xing He Technology Co., Ltd
 * 
 * @author        ZHAO LIMIN
 * @version       1.0.1
 * @since         2025-04
 * HYXHNetsline.ts     标准类，用于记录矢量图：网络线，用于路径描述
 *                     用于导航，通过坐标，完成相关性 
 */
import { ILineIndex } from "./HYXHGeometry";
import { ICartesian } from "./Cartesian"; 
import { PushNumbersToArrays, UNION_NUMBER_ARRAY } from "./HDataType";
import { HPolyline } from "./HYXHPolyline";
import { Check } from "./Check";
import { defined } from "./Defined";
import { HYXHMathUtil } from "./HYXHMathUtil";
import { Cartesian3 } from "./Cartesian3";
import { Queue } from "./Queue";
import { DeveloperError } from "./DeveloperError";
/**
 * 网络线，用于描述复杂网络，类似容器，用于进行导航和索引
 */
export class HNetsPolyline extends HPolyline {   
    /*
     * 线段索引, 用于进行处理
     * 线段索引，用于进行跨连续区域关联
     */
    public linesIndices: ILineIndex;
    constructor() {
        super();
    }

    public generateLinesIndices(): UNION_NUMBER_ARRAY {
        if (this.paths.size == 0) {
            return;
        }
        let indices = new Array<number>();
        for (let key of this.paths.keys()) {
            let path = this.paths.get(key);
            if (path == null) {
                continue;
            }
            if (path.length == 0) {
                continue;
            }
            let lineindices = path.generateToLinesIndices(key);
            if (lineindices == null) {
                continue; 
            }
            if(lineindices.length == 0) {
                continue; 
            }
            indices.push(...lineindices);
        }
        let new_indices = new Array<number>();
        /* 生成跨线段数据连接点 */
        for (let i = 0; i < indices.length; i += 2) {
            let s_layer = indices[i];
            let s_point = indices[i + 1]; 
            let j = i + 2;
            while (j < indices.length) {
                let _s_layer = indices[j];
                if( _s_layer != s_layer) {
                    break;    
                }
                j += 2;
            }
            if (j >= indices.length) {
               break; 
            }
            while( j < indices.length) {
                let _js_layer = indices[j];
                let _js_point = indices[j + 1];
                /* 建立关联 */
                if (this.equalsPosition(s_layer, s_point, _js_layer, _js_point) && (s_layer != _js_layer) ) {
                    new_indices.push(...[s_layer, s_point, _js_layer, _js_point]);
                }
                j += 2;
            }
        }
        if( new_indices.length > 0) {
            indices.push(...new_indices);
        }

        /* 生成索引 */
        if(defined(this.linesIndices)) {
            /* 释放 */
            this.linesIndices.indices = null;
        }
        this.linesIndices = new HNetsPolylineIndex(indices);
        return indices;
    }

    public equalsPosition(slayer: number, sIndex: number, elayer: number, eIndex: number): boolean {
        let spoint = this.indexPoints(slayer, sIndex);
        let epoint = this.indexPoints(elayer, eIndex);
        if (!defined(spoint) || !defined(epoint)) {
            return false;
        }
        return Cartesian3.equalsEpsilon(spoint, epoint, HYXHMathUtil.EPSILON2); 
    }

    /**
     * 更新
     */
    public update(): boolean {
        this.generateLinesIndices();
        return true;
    }
    /**
     * 更新
     */
    public pushIndexLine(slayer: number, spointIndex: number, elayer: number, epointIndex: number){
        Check.defined("linesIndices", this.linesIndices);
        this.linesIndices.pushIndexLine(slayer, spointIndex, elayer, epointIndex);
    }

    /**
     * 根据点，查询
     * @param layer 层
     * @param pointIndex 点索引
     */
    public indexPoints(layer: number, pointIndex: number): ICartesian | undefined {
        if (this.paths.size == 0) {
            return undefined;
        }
        if ( this.paths.has(layer) === false) {
           return undefined; 
        }
        let path = this.paths.get(layer);
        if (!defined(path)) {
            return undefined;
        }

        const length = this.getPathSize(layer);
        if (!defined(length)) {
            return undefined;
        }
        let _start_index = pointIndex >= 0 ? pointIndex: (length + pointIndex);

        return path.getPoint(_start_index);
    }

    public getPathSize(layer: number): number | undefined {
        if (!defined(this.paths)) {
            return undefined;
        }
        if (this.paths.size == 0) {
            return undefined;
        }
        if ( this.paths.has(layer) === false) {
           return undefined; 
        }
        let path = this.paths.get(layer);
        if (!defined(path)) {
            return undefined;
        }
        return path.length;
    }

    /**
     * 根据开始点和结束点，获得点集合的路径
     * @param layer            图层
     * @param pointStartIndex  开始点索引
     * @param pointEndIndex    结束点索引
     * @returns 如果成功返回点路径，否则返回undefined
     */
    public indexPointsPath(layer: number,
                           pointStartIndex: number,
                           pointEndIndex: number): Array<ICartesian> | undefined {
        let path_points = new Array<ICartesian>();
        if (!defined(layer) || !defined(pointStartIndex) || !defined(pointEndIndex)) {
            return undefined;
        }

        if (!defined(this.paths)) {
            return undefined;
        }

        if (this.paths.size == 0) {
            return undefined;    
        }

        const length = this.getPathSize(layer);
        if (!defined(length)) {
            return undefined;
        }

        let _start_index = pointStartIndex >= 0 ? pointStartIndex: (length + pointStartIndex);
        let _end_index = pointEndIndex >= 0 ? pointEndIndex: (length + pointEndIndex);

        for (let i = Math.min(_start_index, _end_index); i <= Math.max(_start_index, _end_index); i++) {
            let _point = this.indexPoints(layer, i);
            if (!defined(_point)) {
                continue;
            }
            path_points.push(_point);
        }
        return path_points;                    
    }
    /**
     * 获得下一个点
     * @param layer 层 
     * @param cpointIndex   当前点索引 
     * @param direction     方向
     * @param pointStartIndex   开始点索引
     * @param pointEndIndex     
     * @returns 
     */
    public getNextPoint(
        layer: number,
        cpointIndex: number,
        direction: number,
        pointStartIndex: number,
        pointEndIndex: number): {position:ICartesian, nextindex:number} | undefined {        
        
        if (!defined(layer) || !defined(pointStartIndex) || !defined(pointEndIndex)) {
            return undefined;
        }

        if (!defined(this.paths)) {
            return undefined;
        }

        if (this.paths.size == 0) {
            return undefined;    
        }

        const length = this.getPathSize(layer);
        if (!defined(length)) {
            return undefined;
        }

        let _start_index = pointStartIndex >= 0 ? pointStartIndex: (length + pointStartIndex);
        let _end_index = pointEndIndex >= 0 ? pointEndIndex: (length + pointEndIndex);

        if (direction == 1) {
            /* 正向 */    
            if ( (_start_index <= _end_index) && (cpointIndex < _end_index ) ) {
                cpointIndex++;
            } else if ( (_start_index > _end_index) && (cpointIndex > _end_index ) ) {
                cpointIndex--;
            }
        } else if (direction == -1) {
            /* 反向 */    
            if ( (_start_index <= _end_index) && (cpointIndex > _start_index ) ) {
                cpointIndex--;
            } else if ( (_start_index > _end_index) && (cpointIndex < _start_index ) ) {
                cpointIndex++;
            }
        }
        let _point = this.indexPoints(layer, cpointIndex);
        if (!defined(_point)) {
            return undefined;
        }
        return {position: _point, nextindex: cpointIndex};        
    }

    /**
     * 根据坐标 反差点的位置，如果不存在返回[]
     * @param poistion 
     */
    public indexPointIndicate(poistion: ICartesian): Array<number>{
        Check.defined("poistion", poistion); 
        if (this.paths.size == 0) {
            return;
        }
        for (let key of this.paths.keys()) {
            let path = this.paths.get(key);
            if (path == null) {
                continue;
            } 
            let _index_po = path.find(poistion);
            if ( _index_po.length <= 0 ) {
                continue;
            }
            return [key, _index_po[0]];
        }
        return [];
    }

    public interpolationForStraightLine(segmentCount: number){
        Check.defined("segmentCount", segmentCount);
        Check.defined("linesIndices", this.linesIndices);
        if (this.paths.size == 0) {
            return;
        }
        for (let key of this.paths.keys()) {
            let path = this.paths.get(key);
            if (path == null) {
                continue;
            } 
            path.interpolationForStraightLine(segmentCount);
        }
        /* 更新索引 */
        this.update();
    }

    public interpolationDistanceForStraightLine(distance: number){
        Check.defined("distance", distance);       
        
        if (this.paths.size == 0) {
            return;
        }
        for (let key of this.paths.keys()) {
            let path = this.paths.get(key);
            if (path == null) {
                continue;
            } 
            path.interpolationDistForStraightLine(distance);
        }
        /* 更新索引 */
       this.update();
    }

    /**
     * 检索附近的连线
     * @param slayer            图层
     * @param spointIndex       点索引
     * @returns 
     */
    public indexNearLines(slayer: number, spointIndex: number): Array<number> {
        Check.defined("linesIndices", this.linesIndices);
        Check.defined("slayer", slayer);
        Check.typeOf.number("slayer", slayer);
        Check.defined("spointIndex", spointIndex);
        Check.typeOf.number("spointIndex", spointIndex);
        /* 发现相邻路线 */
        let _cursor_nexts = this.linesIndices.indexLines(slayer, spointIndex) as number[];
        if (!defined(_cursor_nexts)) {
            return [];
        }
        if (_cursor_nexts.length == 0) {
            return [];
        }
        /* 临时 */
        let _temp_path_logs = new Array<number>();
       
        let _cursor_nexts_near = new Array<number>();

        let queue = new Queue<Float32Array>();
        for (let i = 0; i < _cursor_nexts.length; i += 4) {
           let _line = new Float32Array([_cursor_nexts[i], 
                                         _cursor_nexts[i + 1],
                                         _cursor_nexts[i + 2],
                                         _cursor_nexts[i + 3]]);
           queue.enqueue(_line); 
        }

        while (!queue.isEmpty()) {
            let cursor_line = queue.dequeue();
            if (!defined(cursor_line)) {
                continue;
            }
            if(cursor_line.length == 0) {
                continue; 
            }
            let _slayer = cursor_line[0];
            let _spointIndex = cursor_line[1];
            let _elayer = cursor_line[2];
            let _epointIndex = cursor_line[3];
            
            if (this.equalsPosition(_slayer, _spointIndex, _elayer, _epointIndex) ) {
                let _t_cursor_nexts = this.linesIndices.indexLines(_elayer, _epointIndex) as number[];
                if (!defined(_t_cursor_nexts)) {
                    continue; 
                }
                if (_t_cursor_nexts.length == 0) {
                    continue; 
                }
                for (let i = 0; i < _t_cursor_nexts.length; i += 4) {
                    let _next_layer = _t_cursor_nexts[i + 2];
                    let _next_pointIndex = _t_cursor_nexts[i + 3];

                    if ( _next_layer == _elayer && _next_pointIndex == _epointIndex) {
                        _next_layer = _t_cursor_nexts[i];
                        _next_pointIndex = _t_cursor_nexts[i];
                    }
                    if(this.hasPoint(_temp_path_logs, _next_layer, _next_pointIndex)) {
                        continue;
                    }

                    let _line = new Float32Array(
                        [_slayer, 
                        _spointIndex,
                        _next_layer,
                        _next_pointIndex
                    ]);
                    queue.enqueue(_line); 
                    /* 记录遍历路径 */
                    _temp_path_logs.push(...[ _slayer, _spointIndex, _elayer, _epointIndex]);
                    /* 记录遍历路径 */
                    _temp_path_logs.push(...[ _slayer, _spointIndex, _next_layer, _next_pointIndex]);
                }
             } else {
                _cursor_nexts_near.push(...[_slayer, _spointIndex, _elayer, _epointIndex]);
                _temp_path_logs.push(...[ _slayer, _spointIndex, _elayer, _epointIndex]);
            }            
        }         
        _temp_path_logs.splice(0, _temp_path_logs.length);
        _temp_path_logs.length = 0;
        return _cursor_nexts_near;
    }

    public navigationMinDist(
        slayer: number, sPointIndex: number,
        eLayer: number, ePointIndex: number): Array<ICartesian>| null {
        
        let nvai_paths =  this.navigation(slayer, sPointIndex, eLayer, ePointIndex);
        if (nvai_paths.length == 0) {
            return null;
        }
        let min_path = null;
        let min_distance = 0;
        for (let nvai_path of nvai_paths) { 
            if (!defined(nvai_path)) {
                continue;
            }
            if (nvai_path.length == 0) {
                continue;
            }
            let distance = nvai_path.distance();
            if (min_path == null) {
                min_path = nvai_path;
                min_distance = distance;
            } else if ( min_distance> distance  ){
                min_path = nvai_path;
                min_distance = distance;
            }
        }
        
        if (!defined(min_path)) {
            return null;
        }
        if (!defined(min_path.path)) {
            return null;
        }
        const length_path = min_path.path.length;
        let points = new Array<ICartesian>();
        for (let i = 0; i < length_path; i += 2) {
           const layer = min_path.path[i];
           const index = min_path.path[i + 1];
           let point = this.indexPoints(layer, index);
           if (!defined(point)) {
               continue;
           }
           points.push(point); 
        }
        return points;
    }

    public navigationMaxDist(
        slayer: number, sPointIndex: number,
        eLayer: number, ePointIndex: number): Array<ICartesian>| null {
        
        let nvai_paths =  this.navigation(slayer, sPointIndex, eLayer, ePointIndex);
        if (nvai_paths.length == 0) {
            return null;
        }
        let max_path = null;
        let max_distance = 0;
        for (let nvai_path of nvai_paths) { 
            if (!defined(nvai_path)) {
                continue;
            }
            if (nvai_path.length == 0) {
                continue;
            }
            let distance = nvai_path.distance();
            if (max_path == null) {
                max_path = nvai_path;
                max_distance = distance;
            } else if ( max_distance < distance  ){
                max_path = nvai_path;
                max_distance = distance;
            }
        }
        
        if (!defined(max_path)) {
            return null;
        }
        if (!defined(max_path.path)) {
            return null;
        }
        const length_path = max_path.path.length;
        let points = new Array<ICartesian>();
        for (let i = 0; i < length_path; i += 2) {
           const layer = max_path.path[i];
           const index = max_path.path[i + 1];
           let point = this.indexPoints(layer, index);
           if (!defined(point)) {
               continue;
           }
           points.push(point); 
        }
        return points;
    }

    public navigationRandomDist(
        slayer: number, sPointIndex: number,
        eLayer: number, ePointIndex: number): Array<ICartesian>| null {
        
        let nvai_paths =  this.navigation(slayer, sPointIndex, eLayer, ePointIndex);
        if (nvai_paths.length == 0) {
            return null;
        }

        let selected = Math.floor(Math.random() * nvai_paths.length);
        let min_path = nvai_paths[selected];
        const length_path = min_path.path.length;
        let points = new Array<ICartesian>();
        for (let i = 0; i < length_path; i += 2) {
           const layer = min_path.path[i];
           const index = min_path.path[i + 1];
           let point = this.indexPoints(layer, index);
           if (!defined(point)) {
               continue;
           }
           points.push(point); 
        }
        return points;
    }

    public navigationWithPathDist(
        slayer: number, sPointIndex: number,
        path:number[], 
        cursor: number): Array<ICartesian>| null {
        Check.defined("path", path);
        Check.typeOf.array("path", path);
        Check.defined("cursor", cursor);
        Check.typeOf.number("cursor", cursor);
        if (path.length < 2) {
            return [];
        }
        if (cursor > (path.length - 1)) {
            return [];
        }

        return this.navigationMinDist(
            slayer, sPointIndex,
            path[cursor], path[cursor + 1]
        );
    }

    /**
     * 导航
     * 从指定点，到指定点，进行导航
     * 根据点，读取相互关联的线段的index，用于进行遍历, 返回值是
     * [[layer0,index0, layer1, index1]], 通过读取确定路径，
     * @param slayer 
     * @param sPointIndex 
     * @param eLayer 
     * @param ePointIndex 
     * @returns 
     */
    public navigation(
        slayer: number, sPointIndex: number,  
        eLayer: number, ePointIndex: number): Array<NavigationPath> {
        let nvai_path = new Array<NavigationPath>();
        if (this.paths.size == 0) {
           return nvai_path;
        }
        if ( this.paths.has(slayer) === false) {
           return nvai_path;
        }
        if ( this.paths.has(eLayer) === false) {
           return nvai_path;
        }
        if ( (slayer == eLayer) && (sPointIndex == ePointIndex)  ) {
           return nvai_path;
        }
        if (this.equalsPosition(slayer, sPointIndex, eLayer, ePointIndex) ) {
           return nvai_path; 
        }
        let _nvai_path_log = new Array<number>();
        /* 建立堆栈 */
        let queue = new Queue<NavigationPath>();
        
        let _cursor_nexts = this.linesIndices.indexLines(slayer, sPointIndex) as number[];
        if (!defined(_cursor_nexts)) {
           return nvai_path;
        }
        if (_cursor_nexts.length == 0) {
           return nvai_path; 
        }
        /* 标记 */
        _nvai_path_log.push(slayer, sPointIndex);
        /* next 入队, 并根据节点，选出路径（多条，并选择最短） */
        for (let i = 0; i < _cursor_nexts.length; i += 4) {
            let nvai_path = new NavigationPath(this);
            nvai_path.pushPoints(slayer, sPointIndex);
            nvai_path.pushPoints(_cursor_nexts[i+2], _cursor_nexts[i + 3]);           

            /* 入队 */
            queue.enqueue(nvai_path); 
        }
        let _temp_buffer_nvai_path =  new NavigationPath(this);
        while (!queue.isEmpty()) {
            let cusor_path_navi = queue.dequeue();
            if(!defined(cusor_path_navi)) {
                continue;
            }
            if(cusor_path_navi.length === 0) {
                continue; 
            }
            /* 保存当前路径到临时缓冲区 */
            _temp_buffer_nvai_path.clear();  
            _temp_buffer_nvai_path.pushPoints(...cusor_path_navi.path);
            let _last_point = cusor_path_navi.pop();
            if(!defined(_last_point)) {
                /* 此路径排除 */
                continue;
            }
            if ( ( _last_point[0] == eLayer) && (_last_point[1] == ePointIndex ) ) {
                /* 搜寻到路径 */
                cusor_path_navi.pushPoints( ..._last_point );
                nvai_path.push(cusor_path_navi);
                /* 记录 */
                _nvai_path_log.push(..._last_point);
                continue;
            } else if ( this.equalsPosition(_last_point[0], _last_point[1], eLayer, ePointIndex) ) {
                /* 搜寻到路径 */
                cusor_path_navi.pushPoints(..._last_point );
                nvai_path.push(cusor_path_navi); 
                /* 记录 */
                _nvai_path_log.push(..._last_point);
                continue;
            }
            /* 获得 */
            _cursor_nexts = this.linesIndices.indexLines(_last_point[0], _last_point[1]) as number[];
            if (!defined(_cursor_nexts)) {
                continue;
            }
            if (_cursor_nexts.length == 0) {
                continue;
            }
            if (_cursor_nexts.length < 4) {
                continue;
            }
                    
            let new_pos = false;
            for(let i = 0; i < _cursor_nexts.length; i += 4) {
                let _next_layer = _cursor_nexts[i + 2];
                let _next_point_index = _cursor_nexts[i + 3];
                if ((_next_layer == _last_point[0]) &&
                    (_next_point_index == _last_point[1]) ){
                    _next_layer = _cursor_nexts[i];
                    _next_point_index = _cursor_nexts[i + 1 ];
                }
                if ((_next_layer == _last_point[0]) &&
                    (_next_point_index == _last_point[1]) ){
                    continue;
                }
                
                if ( this.hasPoint(_nvai_path_log, _next_layer, _next_point_index)){
                    continue;
                }
                if (!new_pos){
                    cusor_path_navi.push(_last_point[0], _last_point[1]);
                    cusor_path_navi.push(_next_layer, _next_point_index);
                    /* 入队 */
                    queue.enqueue(cusor_path_navi);

                    /* 记录 */
                    _nvai_path_log.push(..._last_point);
                    new_pos = true;
                } else {                    
                    let _new_other_path_navi = new NavigationPath(this);
                    /* 复制之前 */
                    _new_other_path_navi.pushPoints(..._temp_buffer_nvai_path.path);
                    _new_other_path_navi.push(_next_layer, _next_point_index);
                    /* 入队 */
                    queue.enqueue(_new_other_path_navi);
                    /* 记录 */
                    _nvai_path_log.push(..._last_point);
                    /* 记录 */
                    _nvai_path_log.push(_next_layer, _next_point_index);
                }    
            }
            _temp_buffer_nvai_path.clear(); 
            if (!new_pos) {
                /* 此路径排除 */                
                cusor_path_navi.clear();
            }
        }
        /* 释放，并回收内存 */
        _nvai_path_log.splice(0, _nvai_path_log.length);
        _nvai_path_log.length = 0;
        _temp_buffer_nvai_path.clear();
        return nvai_path;
    }

    public hasPoint(log:Array<number>, layer: number, pointIndex: number): boolean {
        if (log.length == 0) {
            return false;        
        }
        for (let i = 0; i < log.length; i += 2) {
            let _layer = log[i];
            let _pointIndex = log[i + 1];
            if ((_layer == layer) && (_pointIndex == pointIndex)) {
                return true;
            } 
        }
        return false;
    }

    public hasline(log:Array<number>, slayer: number, spointIndex: number, elayer: number, epointIndex: number): boolean {
        if (log.length == 0) {
            return false;        
        }
        for (let i = 0; i < log.length; i += 2) {
            let _slayer = log[i];
            let _spointIndex = log[i + 1];
            let _elayer = log[i + 2];
            let _epointIndex = log[i + 3];

            if ((_slayer == slayer) && 
                (_spointIndex == spointIndex) &&
                (_elayer == elayer) && 
                (_epointIndex == epointIndex)) {
                return true;
            }
            if ((_slayer == elayer) &&
                (_spointIndex == epointIndex) &&
                (_elayer == slayer) &&
                (_epointIndex == spointIndex)) {
                return true;
            }  
        }
        return false;
    }

    public multiplyComponents(scale: ICartesian): void {
        if (!defined(scale)) {
            throw new DeveloperError("scale 未定义"); 
        }

        for (let key of this.paths.keys()) {
            let path = this.paths.get(key);
            if (path == null) {
                continue;
            } 
            path.multiplyComponents(scale);
        }       
    }
    /**偏移 */
    public add(rotation: ICartesian): void {
        if (!defined(rotation)) {
            throw new DeveloperError("rotation 未定义"); 
        }
        for (let key of this.paths.keys()) {
            let path = this.paths.get(key);
            if (path == null) {
                continue;
            } 
            path.add(rotation);
        }  
    }
}
/* 导航路径 */
export class NavigationPath {
    constructor(network : HNetsPolyline) {
        this.path = new Array<number>();
        this.length = 0; 
        this._network = network;
    }
    public path: Array<number>;
    public length: number;

    private _network : HNetsPolyline;
    

    public push(layer: number, pointIndex: number) {
        this.path.push(...[layer, pointIndex]);
        this.length++;
    }

    public pushPoints(...items: number[] ) {
        this.path.push(...items);
        this.length += items.length;
    }
    public pop(): [number, number] | undefined {
        if (this.path.length == 0) {
            return undefined;
        }
        this.length -= 2;
        let pop_nums = [this.path.pop(),this.path.pop()];
        return [pop_nums[1], pop_nums[0]];
    }

    public hasPoint(_layer: number, _pointIndex: number): boolean {
        Check.defined("_layer", _layer);
        Check.defined("_pointIndex", _pointIndex);

        for (let i = 0; i < this.path.length; i += 2){
            const _cursor_layer = this.path[i];
            const _cursor_pointindex = this.path[i + 1];
            if ((_layer === _cursor_layer) &&
                (_cursor_pointindex === _pointIndex)){
                return true;
            }
        //     if (this._network.equalsPosition(_layer, _pointIndex, _cursor_layer, _cursor_pointindex)){
        //         return true;
        //     }
        }

    }

    public distance() : number {
        if (this.path.length == 0) {
            return 0.0; 
        }
        let dist = 0.0;
        for (let i = 0; i < this.path.length; i += 2) {
            let slayer = this.path[i];
            let sPointIndex = this.path[i + 1];
            let elayer = this.path[i + 2]; 
            let ePointIndex = this.path[i + 3];
            if ( (slayer == elayer) && (sPointIndex == ePointIndex) ) {
                continue; 
            }
            let spoint = this._network.indexPoints(slayer, sPointIndex);
            if (!defined(spoint)) {
                continue; 
            }
            let epoint = this._network.indexPoints(elayer, ePointIndex);
            if (!defined(epoint)) {
                continue; 
            }
            dist += Cartesian3.distance(spoint, epoint);
        }
        return dist;
    }

    public clear() {
        Check.defined("this.path", this.path);
        if (this.path.length > 0) {
            this.path.splice(0, this.path.length);
            this.length = 0;
        }
    }
}

export class HNetsPolylineIndex implements ILineIndex {
    public indices: Uint32Array;
    constructor(options: UNION_NUMBER_ARRAY) {
        this.indices = new Uint32Array(options);
    }
    public pushIndexLine(slayer: number, spointIndex: number, elayer: number, epointIndex: number) {
        Check.defined("indices", this.indices);
        this.indices = PushNumbersToArrays(this.indices, slayer, spointIndex, elayer, epointIndex) as Uint32Array;        
    }
    /**
     * 查询, 用于确定连接点
     * @param layer 
     * @param pointIndex 
     */
    public indexLines(layer: number, pointIndex: number): UNION_NUMBER_ARRAY | undefined {
        if (this.indices.length == 0) {
            return undefined;
        }
        let result = new Array<number>();
        let cursor_index = 0;        
        while(cursor_index < this.indices.length) {
            const s_layer = this.indices[cursor_index++]; 
            const s_point = this.indices[cursor_index++]; 
            const e_layer = this.indices[cursor_index++]; 
            const e_point = this.indices[cursor_index++];
            if ((s_layer == layer) && (s_point == pointIndex)) {
                result.push(s_layer, s_point, e_layer, e_point);
            } else if ((e_layer == layer) && (e_point == pointIndex)) {
                result.push(e_layer, e_point, s_layer, s_point); 
            }          
        }
        return result;
    }

    public indexLinesExude(layer:number, pointIndex: number, elayer: number, epointIndex: number): UNION_NUMBER_ARRAY{
        if (this.indices.length == 0) {
            return undefined;
        }
        let result = new Array<number>();
        let cursor_index = 0;
        while(cursor_index < this.indices.length) {
           const s_layer = this.indices[cursor_index++]; 
           const s_point = this.indices[cursor_index++]; 
           const e_layer = this.indices[cursor_index++]; 
           const e_point = this.indices[cursor_index++];
           if ((s_layer == layer) && (s_point == pointIndex)) {
               if ((e_layer == elayer) && (e_point == epointIndex)) {
                  continue; 
               }
               result.push(s_layer, s_point, e_layer, e_point);
           } else if ((e_layer == layer) && (e_point == pointIndex)) {
               if ((s_layer == elayer) && (s_point == epointIndex)) {
                  continue; 
               }
               result.push(e_layer, e_point, s_layer, s_point); 
           }           
        }
        return result;
    }    
}